package ru.xpparty.scanner;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Future;

import ru.xpparty.scanner.model.ScanRequest;

public class Scanner {
    private SocketScannerFactory factory;
    private ExecutorService pool;

    public void setSocketScannerFactory(SocketScannerFactory factory) {
        this.factory = factory;
    }
    
    public void setExecutorService(ExecutorService pool) {
    	this.pool = pool;
    }
    
    public ScanResult scan(ScanRequest request) throws InterruptedException, ExecutionException {
    	List<Future<PortStatus>> result= pool.invokeAll(createScanTasks(request));
        return createResult(request, result);
    }

	private ScanResult createResult(ScanRequest request,
			List<Future<PortStatus>> result) throws InterruptedException,
			ExecutionException {
		ScanResult scanResult = new ScanResult(request.getHost());                
        int port = request.getFrom();
        for (Future<PortStatus> future: result) {
        	scanResult.append(port, future.get());
        	port++;
        }
		return scanResult;
	}

	private List<SocketScannerTask> createScanTasks(ScanRequest request) {
		List<SocketScannerTask> tasks = new ArrayList<SocketScannerTask>();        
        for (int port = request.getFrom(); port <=request.getTo(); port++) {
            tasks.add(new SocketScannerTask(request.getHost(), port));                            
        }
		return tasks;
	}
    
    
    private class SocketScannerTask implements Callable<PortStatus> {
    	private String host;
    	private int port;
    	
    	public SocketScannerTask(String host, int port) {
    		this.host = host;
    		this.port = port;
    	}
    	
		@Override
		public PortStatus call() throws Exception {
			SocketScanner socketScanner = factory.create(host, port);
            return socketScanner.scan();            
		}
    	
    }
}
